1 /* 2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021 3 License: [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License]. 4 Authors: Marcelo S. N. Mancini 5 6 Copyright Marcelo S. N. Mancini 2018 - 2021. 7 Distributed under the CC BY-4.0 License. 8 (See accompanying file LICENSE.txt or copy at 9 https://creativecommons.org/licenses/by/4.0/ 10 */ 11 module hip.util.time; 12 import core.stdc.time; 13 14 version(Windows) 15 { 16 import core.sys.windows.windef; 17 extern(Windows) BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpPerformanceCount) nothrow; 18 extern(Windows) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount) nothrow; 19 } 20 else version(WebAssembly) 21 { 22 extern(C) size_t monotimeNow() @nogc nothrow; 23 } 24 else 25 { 26 import core.stdc.config:c_long; 27 enum CLOCK_MONOTONIC = 1; 28 struct timespec 29 { 30 int tv_sec; //Seconds 31 c_long tv_nsec; //Nanoseconds 32 } 33 extern(C) int clock_gettime(int clock_id, timespec* tm) nothrow; 34 } 35 36 ulong getSystemTime() nothrow 37 { 38 version(Windows) 39 { 40 LARGE_INTEGER counter = void; 41 QueryPerformanceCounter(&counter); 42 return counter.QuadPart * 1_000_000_000; //Convert to nanos 43 } 44 else version(WebAssembly) 45 { 46 return monotimeNow(); 47 } 48 else 49 { 50 timespec tm = void; 51 if(clock_gettime(CLOCK_MONOTONIC, &tm)) 52 return 0; 53 return cast(size_t)(tm.tv_nsec + tm.tv_sec * 1e9); 54 } 55 } 56 private ulong getSystemTicksPerSecond() nothrow 57 { 58 version(Windows) 59 { 60 LARGE_INTEGER ticksPerSecond = void; 61 QueryPerformanceFrequency(&ticksPerSecond); 62 return ticksPerSecond.QuadPart; 63 } 64 else 65 { 66 return 0; 67 } 68 } 69 70 class HipTime 71 { 72 73 private __gshared ulong startTime; 74 private __gshared ulong ticksPerSecond; 75 protected __gshared long[string] performanceMeasurement; 76 77 static void initialize() 78 { 79 ticksPerSecond = getSystemTicksPerSecond(); 80 startTime = getSystemTime(); 81 } 82 83 static long getCurrentTime() nothrow 84 { 85 ulong time = 0; 86 version(Windows) 87 { 88 time = (getSystemTime() - startTime) / ticksPerSecond; 89 } 90 else 91 time = getSystemTime() - startTime; 92 return time; 93 } 94 95 static float getCurrentTimeAsMilliseconds() nothrow 96 { 97 version(WebAssembly) 98 return cast(float)getCurrentTime(); 99 else 100 return cast(float)getCurrentTime() / 1_000_000; 101 } 102 static float getCurrentTimeAsSeconds() nothrow 103 { 104 version(WebAssembly) 105 return getCurrentTime() / 1_000; 106 else 107 return cast(float)getCurrentTime() / 1_000_000_000; 108 } 109 110 static void initPerformanceMeasurement(string name) 111 { 112 performanceMeasurement[name] = getCurrentTime(); 113 } 114 static void finishPerformanceMeasurement(string name) 115 { 116 // import std.stdio:writeln; 117 // writeln(name, " took ", (getCurrentTime() - performanceMeasurement[name])/1_000_000, "ms"); 118 } 119 120 static struct Profiler 121 { 122 private string name; 123 this(string name){this.name = name;HipTime.initPerformanceMeasurement(name);} 124 ~this(){HipTime.finishPerformanceMeasurement(name);} 125 } 126 static mixin template Profile(string name){mixin("HipTime.Profiler _profile"~name~" = HipTime.Profiler("~name~");");} 127 static mixin template ProfileFunction(){mixin("HipTime.Profiler _profileFunc = HipTime.Profiler(__PRETTY_FUNCTION__);");} 128 } 129 130 float seconds(float v){return v;} 131 float msecs(float v){return v*1_000;} 132 float usecs(float v){return v*1_000_000;} 133 float nsecs(float v){return v*1_000_000_000;}